package loader
{
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.Dictionary;

	
	/**
	 * Base Asset class
	 * ...
	 * @author SChabanov
	 */
	public class Asset extends EventDispatcher
	{
		
		public static const TEXT	:uint = 1;
		public static const RESOURCE:uint = 2;
		
		public var priority:int;
		public var path:String;
		public var name:String;
		public var linfo:LoaderInfo;
		
		
		private var _content:DisplayObject;
		private var _groupName:String;		
		private var _ioErrorString:String = "";
		
		private var _uloader:URLLoader;
		private var _loader:Loader
		
		private var _resourceType:uint;
		private var _isStarted:Boolean = false;
		private var _isLoaded:Boolean = false;
		private var _percentLoaded:Number;

		private var _xmlData:XML;
		
		private var _listeners:Dictionary;
		
		public function Asset(name:String,path:String, priority:int = 0,groupName:String=null)
		{
			this._groupName = groupName;
			this.name	   = name;
			this.priority  = priority;
			this.path 	   = path;
							
			this._listeners = new Dictionary(true);
			if (path.indexOf("xml") != -1)		
			{
				_resourceType = TEXT;
				_uloader = new URLLoader();
				_uloader.dataFormat = URLLoaderDataFormat.TEXT;
				_uloader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				
			}else {
				
				_resourceType = RESOURCE
				_loader = new Loader();
				_loader.contentLoaderInfo.addEventListener(Event.INIT, onInit, false, 0, true);
				_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			}
			
		}
		
						
		private function onInit(e:Event):void 
		{			
			dispatchEvent(e);
		}
		
		public function start():void
		{
			if (_isLoaded)
			{				
				dispatchEvent(new Event(Event.COMPLETE));
				return;
			}
			if (!_isStarted) 
			{
				if (_uloader)
				{
					_uloader.addEventListener(Event.COMPLETE, onCompleteLoadHandler, false, 0, true);
					_uloader.addEventListener(ProgressEvent.PROGRESS, progressHandler, false, 0, true);
					_uloader.load(new URLRequest(path));
				}else if(_loader){
					_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteLoadHandler, false, 0, true);
					_loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler, false, 0, true);
					_loader.load(new URLRequest(path));
				}
				
				_isStarted = true;
			}
		
		}
		
		public function destroy():void
		{
			if (_loader)
			{
				if (linfo.content.parent) linfo.content.parent.removeChild(linfo.content);
				_loader.unloadAndStop();
			}else if(_uloader){
				_uloader.close();
			}
			_isLoaded = false;
			clearListeners();
			
		}
		
		private function ioErrorHandler(e:IOErrorEvent):void
		{
			_ioErrorString = e.text;
			if (_loader)
			{
				_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onCompleteLoadHandler);
				_loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
			}else {
				_uloader.removeEventListener(Event.COMPLETE, onCompleteLoadHandler);
				_uloader.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
				_xmlData = new XML("<ioerror>"+_ioErrorString+"</ioerror>")
			}
			_percentLoaded = 0;
			_isLoaded = false;
			_isStarted = false;
			dispatchEvent(new Event(Event.COMPLETE));
		}
		
		private function progressHandler(e:ProgressEvent):void
		{
			_percentLoaded = (e.bytesLoaded / e.bytesTotal) * 100;
			dispatchEvent(e);
		}
		
		private function onCompleteLoadHandler(e:Event):void
		{
			_isLoaded = true;
			_isStarted = false;
			if (_loader)
			{
				_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onCompleteLoadHandler);
				_loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
				linfo = _loader.contentLoaderInfo;
				_content = _loader.contentLoaderInfo.content;
			}else if (_uloader) {
				_uloader.removeEventListener(Event.COMPLETE, onCompleteLoadHandler);
				_uloader.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
				_xmlData = XML(_uloader.data);
			}
			dispatchEvent(e);
			clearListeners();
		}
			
		private function clearListeners():void
		{
			for (var type:String in _listeners) 
			{
				super.removeEventListener(type, _listeners[type]);
				
			}
			_listeners = null;
			_listeners = new Dictionary(true);
		}
		
		/**
		 * @overrides
		 */
		override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void 
		{
			_listeners[type] = listener;
			super.addEventListener(type, listener, useCapture, priority, useWeakReference);
		}
		
		override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void 
		{
			delete _listeners[type];
			super.removeEventListener(type, listener, useCapture);
		}
		/**
		 * 
		 */
		
		public function get percentLoaded():Number
		{
			return _percentLoaded;
		}
		
		public function get isLoaded():Boolean
		{
			return _isLoaded;
		}
		
		public function get ioErrorString():String 
		{
			return _ioErrorString;
		}
		
		public function get groupName():String 
		{
			return _groupName;
		}
		
		public function get content():DisplayObject 
		{
			return _content;
		}
						
		public function get isStarted():Boolean 
		{
			return _isStarted;
		}
		
		public function get resourceType():uint 
		{
			return _resourceType;
		}
		
		public function get xmlData():XML 
		{
			return _xmlData;
		}
	
	}

}